#include <iostream>
#include <fstream>
#include <queue>
#include <list>
#include <sstream>
//#include <boost/thread/thread.hpp>
//#include <boost/thread/mutex.hpp>
//#include <boost/bind.hpp>
//#include <boost/tr1/memory.hpp>

#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>

#include <ctime>
#include <cstdio>


#include "URLDiskClassP.h"

using namespace std;

URLDiskClassP::URLDiskClassP(){
//	diskIO.open("fileTeste.txt", ios::in | ios::out | ios::binary); //ios::in | ios::out | ios::binary
//	if(diskIO == NULL) cout << "Erro.. " << endl;

	openDisks();
	
    pSaveDiskReadPos = fopen64("pSaveDiskReadPos","r+");  //Leitura e escreve
    if (pSaveDiskReadPos == NULL){
    	cout << "Erro ao abrir o arquivo de disco pSaveDiskReadPos... " << endl;
    	exit(1);
    }
    
    
    URLBuffer_IN = new _t_URL;
    URLBuffer_OUT = new _t_URL;
}

URLDiskClassP::~URLDiskClassP(){

	closeDisks();

	if(pSaveDiskReadPos != NULL) fclose(pSaveDiskReadPos);
	
	delete URLBuffer_IN;
	delete URLBuffer_OUT;
}


void URLDiskClassP::openDisks(void){
	
	cout << "Abrindo discos ... " << endl;
	
	pDisk[0] = fopen64 ("DiscoURL_P0.bin","ab+");  //Leitura e "escrita no final"
	pDisk[1] = fopen64 ("DiscoURL_P1.bin","ab+");  //Leitura e "escrita no final"
	pDisk[2] = fopen64 ("DiscoURL_P2.bin","ab+");  //Leitura e "escrita no final"
	pDisk[3] = fopen64 ("DiscoURL_P3.bin","ab+");  //Leitura e "escrita no final"
	pDisk[4] = fopen64 ("DiscoURL_P4.bin","ab+");  //Leitura e "escrita no final"
	pDisk[5] = fopen64 ("DiscoURL_P5.bin","ab+");  //Leitura e "escrita no final"
	
	for(int i=0; i<6; i++)
    if (pDisk[i] == NULL){
    	cout << "Erro ao abrir o arquivo de disco: " << i << endl;
    	exit(1);
    }
	
    return;
}



void URLDiskClassP::closeDisks(void){
	for(int i=0; i<6; i++) if(pDisk[i] != NULL) fclose(pDisk[i]);	
	return;
}




void URLDiskClassP::writeDisk(URL t){
//	boost::mutex::scoped_lock urlDiskClassLock(urlDiskClassMutex);
	
// Estrutura da URL:
//		std::string path;
//		std::string dominio;
//		std::string protocol;	
//		short depth;  ---> Nao precisa salvar !!!
	try{
		
		string _path;
		string _dominio;
		string _protocolo;
		_path = (t.get_path().size() >= 230) ? t.get_path().substr(0,229) : t.get_path();
		_dominio = (t.get_dominio().size() >= 60) ? t.get_dominio().substr(0,59) : t.get_dominio();
		_protocolo = (t.get_protocol().size() >= 10) ? t.get_protocol().substr(0,9) : t.get_protocol();
		
		//cout << "Aqui, URLDiskClass::writeDisk() " << endl;
		strcpy(URLBuffer_OUT->t_path, _path.c_str());
		strcpy(URLBuffer_OUT->t_dominio, _dominio.c_str());
		strcpy(URLBuffer_OUT->t_protocol, _protocolo.c_str());
	
		int res;
		res = fwrite(URLBuffer_OUT, sizeof(_t_URL), 1, pDisk[0] );
		
		
		if(res != 1) cout << "Erro ao gravar em URLDiskClass::writeDisk() " <<  endl;
		
	//    fflush (pDisk);    // flushing required
	//    cout << res << endl;
		
		
	}catch(...){
		cout << "Erro no URLDiskClass::writeDisk " << endl;
	}
//	delete URLBuffer_OUT;
}



URL URLDiskClassP::readDisk(void){
//	boost::mutex::scoped_lock urlDiskClassLock(urlDiskClassMutex);
//	URLBuffer_IN = new _t_URL;
//	SEEK_SET	Beginning of file
//	SEEK_CUR	Current position of the file pointer
//	SEEK_END	End of file
	long int pDiskOffset;
  	long int pDiskSize;

//  	fseek (pDisk , 0 , SEEK_END); //vai para o final
  	pDiskSize = ftell (pDisk[0]);  	// Pega o tamanho
  	pDiskSize = pDiskSize / sizeof(_t_URL);
 
   	//Recupera ultima posicao lida
  	long int _savePos;
  	rewind (pSaveDiskReadPos);
  	fscanf (pSaveDiskReadPos, "%ld", &_savePos);
    	
// 	  cout << "DiskSize: " << pDiskSize <<  " elementos" << endl;
//    cout << "Total   : " << pDiskSize*sizeof(_t_URL)/(1024*1024) << " MBytes" << endl;
//    cout << "Total n lido: " << (pDiskSize-_savePos) << endl;
  	
  	if(_savePos > pDiskSize){
  		cout << "Ultima pos lida e tamanho do arquivo nao batem..." << endl;
  		tURL = URL("", "","");
  	    return tURL;  
  	}
  	
  	//cout << "Tamanho nao lido: " << (pDiskSize-_savePos) << endl;
  	
  	//posiciona no lugar a ser lido
  	pDiskOffset = _savePos;
  	_savePos = _savePos + 1;
  	fseek ( pDisk[0] , pDiskOffset*sizeof(_t_URL) , SEEK_SET);
  	fread(URLBuffer_IN, sizeof(_t_URL), 1, pDisk[0]);
  	tURL = URL(URLBuffer_IN->t_dominio, URLBuffer_IN->t_path, URLBuffer_IN->t_protocol );
  	//cout << "URLDiskClass::readDisk URL lida: " << tURL.toString() << endl;
  	//Grava ultima pos lida
  	rewind (pSaveDiskReadPos);
  	fprintf(pSaveDiskReadPos, "%ld", _savePos);//aponta para proximo lugar a ser lido
  	fflush (pSaveDiskReadPos);
//  	delete URLBuffer_IN;
    return tURL;
}



long long URLDiskClassP::size(void){
	long long pDiskSize;
  	fseeko64 (pDisk[0] , 0 , SEEK_END); //vai para o final
  	pDiskSize = ftello64(pDisk[0]);  	// Pega o tamanho
  	pDiskSize = pDiskSize / sizeof(_t_URL);
  	return pDiskSize;
}

long int URLDiskClassP::pos(void){
  	long int _savePos;
  	rewind (pSaveDiskReadPos);
  	fscanf (pSaveDiskReadPos, "%ld", &_savePos);
  	return _savePos;
}

